package com.lrz.answerPlatform.scoring;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.lrz.answerPlatform.model.dto.question.QuestionContentDTO;
import com.lrz.answerPlatform.model.entity.App;
import com.lrz.answerPlatform.model.entity.Question;
import com.lrz.answerPlatform.model.entity.ScoringResult;
import com.lrz.answerPlatform.model.entity.UserAnswer;
import com.lrz.answerPlatform.model.vo.QuestionVO;
import com.lrz.answerPlatform.service.QuestionService;
import com.lrz.answerPlatform.service.ScoringResultService;

import javax.annotation.Resource;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * appType = 1 测试类app
 * scoringStrategy = 0 评分策略为自定义
 */
@ScoringStrategyConfig(appType = 1, scoringStrategy = 0)
public class CustomTestScoringStrategy implements ScoringStrategy {

    @Resource
    private QuestionService questionService;

    @Resource
    private ScoringResultService scoringResultService;

    /**
     * 自定义测试类
     * @param choices
     * @param app
     * @return
     */
    @Override
    public UserAnswer doScore(List<String> choices, App app) {
        //1.先拿到题目列表和结果信息
        Question question = questionService.getOne(
                Wrappers.lambdaQuery(Question.class).eq(Question::getAppId, app.getId())
        );
        List<ScoringResult> scoringResultList = scoringResultService.list(
                Wrappers.lambdaQuery(ScoringResult.class).eq(ScoringResult::getAppId, app.getId())
        );
        //2.统计用户选择的选项依次对应的个数

        //2.1 定义一个哈希表，记录每一个对立结果选项所对应的个数 例如[I跟E对立 I:5  E:10;
        //                                                  S跟N对立 S:10 N:6 ] 哪个权重更高，结果就是哪个
        Map<String, Integer> optionCount = new HashMap<>();
        //2.2 遍历题目列表
        QuestionVO questionVO = QuestionVO.objToVo(question);
        List<QuestionContentDTO> questionContent = questionVO.getQuestionContent();//获取题目列表
        //遍历题目列表 用题目和选项一一对应
        for (int i = 0; i < choices.size(); i++) {
            //获得用户第i个选项
            String userChoices = choices.get(i);
            //获得题目表中第i个题目
            QuestionContentDTO currentQuestion = questionContent.get(i);

            // 找到用户选择的选项对应的 result（如 I/E）
            for (QuestionContentDTO.Option currentQuestionOption : currentQuestion.getOptions()) {
                if (currentQuestionOption.getKey().equals(userChoices)) {
                    //如果选到了对应的结果，就这个选项放入到hash表中计数
                    String resultProp = currentQuestionOption.getResult();
                    optionCount.put(resultProp, optionCount.getOrDefault(resultProp, 0) + 1);
                }
            }


        }
        //循环结束后，optionCount这里存的数值可能就是：{ I: 5   E:10  记录了每一个对立选项对应的个数
        //                                         S:3   N：2
        //                                         T:10   F:6
        //                                         J:10   P:6}
        int maxScore = 0;//初始化最高分
        ScoringResult maxScoreResult = scoringResultList.get(0);//初始化最终结果 默认为第一个
        //3 计算该评分结果四个选项，在optionCount所占的权重，也就是得分（次数）
        for (ScoringResult result : scoringResultList) {
            List<String> resulProptList = JSONUtil.toList(result.getResultProp(), String.class);//将每一个结果的属性转为list 例如：[I,S,T,J]
            int score = resulProptList.stream().mapToInt(prop -> optionCount.getOrDefault(prop, 0)).sum();
            if (score > maxScore) {
                maxScore = score;
                maxScoreResult = result;
            }
        }
        //4.构造返回值，填充答案对象
        UserAnswer userAnswer = new UserAnswer();
        userAnswer.setAppId(app.getId());
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());

        userAnswer.setResultId(maxScoreResult.getId());
        userAnswer.setResultName(maxScoreResult.getResultName());
        userAnswer.setResultDesc(maxScoreResult.getResultDesc());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        userAnswer.setResultPicture(maxScoreResult.getResultPicture());
        return userAnswer;
    }
}


